/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 */

#ifndef BASE_ALGO_FACE_BEST_SELECTOR_FACE_DET_H
#define BASE_ALGO_FACE_BEST_SELECTOR_FACE_DET_H

#include <cstdint>
#include <vector>
#include <unordered_map>
#include <string>
#include <mutex>
#include <memory>
#include <thread>
#include <atomic>
#include <functional>
#include <nlohmann/json.hpp>
#include "hal_struct.h"

namespace El {
namespace Algo {

// 仅基于 HI_AIVSR_TASK_FACE_CAPTURE（无特征）的人脸优选
class FaceBestSelectorFaceDet {
public:
    static FaceBestSelectorFaceDet &GetInstance();

    // 更新配置（可选）
    void UpdateConfig(const nlohmann::json &cfg);

    // 推入一帧 HAL 人脸结果，内部执行轨迹与窗口优选
    // 如产生新的“最佳人脸事件”，返回 true 并填充 outEvent
    bool PushHalResult(const HAL_ALGO_REC_RESULT &halResult,
                       uint32_t imgWidth,
                       uint32_t imgHeight,
                       uint64_t timestampMs,
                       nlohmann::json &outEvent);

    // 设置事件回调：在改进触发或超时触发时，由选择器线程或Push流程调用
    using EventCallback = std::function<void(const nlohmann::json &event)>;
    void SetEventCallback(EventCallback cb);

private:
    struct BBox {
        int x;
        int y;
        int w;
        int h;
    };

    struct Candidate {
        BBox box;
        int quality;     // 0-100
        float confidence; // 0.0-1.0
        uint64_t tsMs;
        float area_ratio; // 相对于整图的归一化面积
        float center_score; // 越靠中心越大 [0,1]
        int track_id;    // 来自 HAL 的真实 track_id
        int track_status; // HAL_TRACK_STATUS_E
    };

    // 不再维护内部追踪结构，直接依赖 HAL 提供的 track_id/track_status

private:
    FaceBestSelectorFaceDet() = default;
    ~FaceBestSelectorFaceDet() = default;
    FaceBestSelectorFaceDet(const FaceBestSelectorFaceDet &) = delete;
    FaceBestSelectorFaceDet &operator=(const FaceBestSelectorFaceDet &) = delete;

    // 内部方法
    static float CenterScore(const BBox &b, uint32_t w, uint32_t h);
    static float AreaRatio(const BBox &b, uint32_t w, uint32_t h);
    static bool IsFaceLabel(const char *label);
    static BBox MakeBox(const HAL_REC_PARAM &p);
    static Candidate MakeCandidate(const HAL_ALGO_REC_RESULT &r, int idx, uint32_t w, uint32_t h, uint64_t ts);
    void CleanupStaleTracks(uint64_t nowMs); // 无状态实现，保留以兼容接口
    void EvalTimeoutAndEmit(uint64_t nowMs);
    void EmitEvent(const Candidate &cand, int trackId, uint32_t imgW, uint32_t imgH, uint64_t ts, const char *reason);

    // 打分比较：质量->置信度->居中性->面积
    static bool BetterThan(const Candidate &a, const Candidate &b);

private:
    // 配置项（默认值）
    uint32_t window_ms_ = 1000;          // 短窗，超时触发参考
    uint32_t early_stop_ms_ = 400;       // 提前结束窗口的等待
    int min_quality_ = 55;               // 最小质量
    float min_area_ratio_ = 0.02f;       // 最小归一化面积
    int improve_delta_q_ = 3;            // 质量相对提升触发
    uint32_t cooldown_ms_ = 2000;        // 触发冷却

    // 状态
    std::mutex mu_;
    // 全局最佳与待定最佳
    bool has_global_best_ = false;
    Candidate global_best_{};
    int global_best_track_id_ = -1;
    uint64_t last_global_emit_ts_ = 0;
    uint64_t last_improve_ts_ = 0;
    uint64_t last_face_seen_ts_ = 0;
    bool has_pending_best_ = false;
    Candidate pending_best_{}; // 最近一段时间内的帧级最佳，用于超时触发

    // 回调与线程
    EventCallback cb_;
    std::unique_ptr<std::thread> worker_;
    std::atomic<bool> running_{false};
    uint32_t img_w_{1024};
    uint32_t img_h_{576};
};

} // namespace Algo
} // namespace El

#endif // BASE_ALGO_FACE_BEST_SELECTOR_FACE_DET_H
